/// <reference path="../types.ts" />
/// <reference path="../helpers.ts" />
/// <reference path="organization.ts" />

module $Xrm.Messages {
    export class RetrieveMultipleRequest extends OrganizationRequest {
        public Query: FetchExpression;

        constructor(query?: FetchExpression) {
            super("RetrieveMultiple");

            this.Query = query;
        }

        GetResponse(responseXml: Document): RetrieveMultipleResponse {
            return new RetrieveMultipleResponse(responseXml);
        }

        ToSoapXml(): string {
            this.Parameters["Query"] = this.Query;

            return super.ToSoapXml();
        }
    }

    export class RetrieveMultipleResponse extends OrganizationResponse {
        public Entities: $Xrm.Entity[];

        constructor(responseXml?: Document) {
            super("RetrieveMultiple", responseXml);

            this.ParseResponse(responseXml);
            this.BindProperties();
        }

        BindProperties(): void {
            super.BindProperties();

            this.Entities = this.Results["Entities"];
        }

        ParseResponse(responseXml: Document): void {
            this.Results = [];

            var rn = _xml.getChildNode(responseXml.firstChild.firstChild.firstChild.firstChild, 'a:Results');
            if (rn != null) {
                var entities = _xml.getChildNode(rn.firstChild, 'b:value');
                if (entities != null && entities.firstChild != null && entities.firstChild.childNodes != null) {
                    var resultsNode = entities.firstChild.childNodes;

                    var parsed = RetrieveMultipleResponse.ParseResults(resultsNode);

                    this.Results["Entities"] = parsed;
                }
            }
        }

        private static GetValueFromXml(type: string, valueNode: any): any {
            switch (type) {
                case "a:OptionSetValue":
                    return new $Xrm.OptionSetValue(parseInt(_xml.getText(valueNode)));

                case "a:EntityReference":
                    var ref = new $Xrm.EntityReference();
                    ref.Id = _xml.getText(valueNode.childNodes[0]);
                    ref.LogicalName = _xml.getText(valueNode.childNodes[1]);
                    ref.Name = _xml.getText(valueNode.childNodes[2]);

                    return ref;

                case "a:Money":
                    var value = parseFloat(_xml.getText(valueNode.childNodes[0]));
                    return new $Xrm.Money(value);

                case "a:AliasedValue":
                    valueNode = _xml.getChildNode(valueNode, "a:Value");
                    type = _xml.getText(_xml.getAttribute(valueNode, "i:type"));

                    return RetrieveMultipleResponse.GetValueFromXml(type, valueNode);
                default:
                    return _xml.getText(valueNode);
            }
        }

        private static ParseResults(resultsNode): $Xrm.Entity[] {
            var results = new Array(resultsNode.length);

            for (var i = 0; i < results.length; i++) {
                var node = resultsNode[i];
                var je = new $Xrm.Entity("");
                //var o = new Array();

                for (var j = 0; j < node.childNodes.length; j++) {
                    switch (node.childNodes[j].nodeName) {
                        case "a:Attributes":
                            var attr = node.childNodes[j];

                            for (var k = 0; k < attr.childNodes.length; k++) {
                                var key = _xml.getText(attr.childNodes[k].firstChild);
                                var type = "";

                                for (var l = 0; l < attr.childNodes[k].childNodes[1].attributes.length; l++) {
                                    if (attr.childNodes[k].childNodes[1].attributes[l].nodeName == "i:type") {
                                        type = _xml.getText(attr.childNodes[k].childNodes[1].attributes[l]);
                                    }
                                }

                                var valueNode = attr.childNodes[k].childNodes[1];
                                var value = RetrieveMultipleResponse.GetValueFromXml(type, valueNode);

                                je[key] = value;
                            }
                            break;

                        case "a:Id":
                            je.Id = _xml.getText(node.childNodes[j]);
                            break;

                        case "a:LogicalName":
                            je.LogicalName = _xml.getText(node.childNodes[j]);
                            break;

                        case "a:FormattedValues":
                            var foVal = node.childNodes[j];

                            for (var k = 0; k < foVal.childNodes.length; k++) {
                                var key = _xml.getText(foVal.childNodes[k].firstChild);
                                je[key].FormattedValue = _xml.getText(foVal.childNodes[k].childNodes[1]);
                            }
                            break;
                    }
                }

                results[i] = je;
            }

            return results;
        }
    }
}